package com.easylinkin.linkappapi.common.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.easylinkin.linkappapi.common.utils.DateUtil;
import com.easylinkin.linkappapi.operatelog.entity.ObjectOperateLog;
import com.easylinkin.linkappapi.quality.dto.ActualMeasureTypeDto;
import com.easylinkin.linkappapi.quality.entity.ActualMeasureItem;
import com.easylinkin.linkappapi.quality.entity.ActualMeasureType;
import com.easylinkin.linkappapi.quality.mapper.ActualMeasureItemMapper;
import com.easylinkin.linkappapi.quality.mapper.ActualMeasureTypeMapper;
import com.easylinkin.linkappapi.security.constant.LinkappUserConstant;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.space.entity.LinkappSpace;
import com.easylinkin.linkappapi.space.service.LinkappSpaceService;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import site.morn.framework.context.AccountContext;
import site.morn.framework.entity.BaseUser;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p></p>
 *
 * @author TongJie
 * @since 2020/4/15 20:53
 */
@Component
public class CommonServiceImpl implements CommonService {

    Logger LOGGER = LoggerFactory.getLogger(CommonServiceImpl.class);
    @Resource
    LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    LinkappSpaceService linkappSpaceService;


    @Autowired
    private ActualMeasureTypeMapper actualMeasureTypeMapper;

    @Autowired
    private ActualMeasureItemMapper actualMeasureItemMapper;

    @Override
    public void setCreateAndModifyInfos(Collection objects) {
        if (CollectionUtils.isEmpty(objects)) {
            LOGGER.info("要设置创建修改信息对象集合为空");
            return;
        }
        BaseUser baseUser = AccountContext.currentUser();
        if (baseUser == null) {
            throw new RuntimeException("登录用户信息为null");
        }
        try {
            for (Object object : objects) {
                setCreateModifyInfo(baseUser, object);
            }

        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException("设置创建和修改人方法执行失败");
        }
    }

    @Override
    public void setModifyInfos(Collection objects) {
        if (CollectionUtils.isEmpty(objects)) {
            LOGGER.info("要设置修改信息对象集合为空");
            return;
        }
        BaseUser baseUser = AccountContext.currentUser();
        try {
            for (Object object : objects) {
                setModifyInfo(baseUser, object);
            }

        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException("设置修改人方法执行失败");
        }
    }

    @Override
    public void setCreateModifyInfo(BaseUser baseUser, Object object)
            throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        try {
            object.getClass().getMethod("setCreateTime", Date.class)
                    .invoke(object, DateUtil.now());
        } catch (Exception e) {

        }
        if (baseUser != null) {
            try {
                object.getClass().getMethod("setCreator", String.class)
                        .invoke(object, String.valueOf(baseUser.getId()));
            } catch (Exception e) {

            }
        }
        setModifyInfo(baseUser, object);
    }



    private void setModifyInfo(BaseUser baseUser, Object object)
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {

        try {
            object.getClass().getMethod("setModifyTime", Date.class)
                    .invoke(object, DateUtil.now());
        } catch (IllegalAccessException e) {

        }
        if (baseUser != null) {
            try {
                object.getClass().getMethod("setModifier", String.class)
                        .invoke(object, String.valueOf(baseUser.getId()));
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void setCreateAndModifyInfo(Object obj) {
        try {
            setCreateModifyInfo(AccountContext.currentUser(), obj);
        } catch (Exception e) {
//            LOGGER.error(e.getMessage(), e);
//            throw new RuntimeException("设置创建和修改人方法执行失败");
        }
    }

    @Override
    public void setTenantIdInfo(Object obj) {
        LinkappUser user = linkappUserContextProducer.getCurrent();
        try {
            if (user != null) {
                obj.getClass().getMethod("setTenantId", String.class)
                        .invoke(obj, String.valueOf(user.getTenantId()));
            }else {
                LOGGER.warn("未获取到当前登录用户");
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException("设置租户ID方法执行失败");
        }

    }

    @Override
    public void setCreateInfo(Object object) {
        try {
            BaseUser baseUser = AccountContext.currentUser();
            try {
                object.getClass().getMethod("setCreateTime", Date.class)
                        .invoke(object, DateUtil.now());
            } catch (Exception e) {
            }
            if (baseUser != null) {
                try {
                    object.getClass().getMethod("setCreator", String.class)
                            .invoke(object, String.valueOf(baseUser.getId()));
                } catch (Exception e) {
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException("设置创建和修改人方法执行失败");
        }
    }

    @Override
    public void setModifyInfo(Object obj) {
        BaseUser baseUser = AccountContext.currentUser();
        try {
            setModifyInfo(baseUser, obj);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException("设置修改人修改时间方法执行失败");
        }
    }

    @Override
    public void setLogUserInfo(ObjectOperateLog objectOperateLog) {
        LinkappUser user = linkappUserContextProducer.getCurrent();
        objectOperateLog.setCreator(user.getId().toString());
        objectOperateLog.setTenantId(user.getTenantId());

        if (StringUtils.isNotEmpty(user.getNickname())) {
            objectOperateLog.setCreatorName(user.getNickname());
        } else {
            objectOperateLog.setCreatorName(user.getUsername());
        }
        objectOperateLog.setCreateTime(new Date());
    }



    @Override
    public List<LinkappSpace> getCurrentUserSpace() {
        LinkappUser currentUser = linkappUserContextProducer.getCurrent();
        Assert.notNull(currentUser,"获取当前用户为空");
        if(LinkappUserConstant.ADMIN_TYPE.equals(currentUser.getType())){
            return linkappSpaceService.selectLinkappSpaceList(new LinkappSpace());
        }else{
           return linkappUserContextProducer.getCurrentUserSpace(currentUser.getId());
        }
    }

    @Override
    public List<String> getCurrentUserSpaceIds() {
        List<LinkappSpace> spaces = getCurrentUserSpace();
        if (ObjectUtils.isEmpty(spaces)) {
            return new ArrayList<>();
        }
        return spaces.stream().map(LinkappSpace::getId).collect(Collectors.toList());
    }

    @Override
    public void sleep(Double seconds) {
        if (seconds == null && seconds <= 0) {
            return;
        }
        Double delayTimeMilliSecond = seconds * 1000;

        try {
            TimeUnit.MILLISECONDS.sleep(delayTimeMilliSecond.longValue());
        } catch (InterruptedException e) {
            LOGGER.error("设置休眠时间失败，详情：", e);
        }
    }

    @Override
    public void copyActualMeasureTypeItem(LinkappTenant tenant) {
        QueryWrapper<ActualMeasureType> qw = new QueryWrapper<>();
        qw.eq("delete_state", 1);
        qw.isNull("tenant_id");
        qw.orderByAsc("id");
        List<ActualMeasureType> actualMeasureTypeLs = actualMeasureTypeMapper.selectList(qw);

        QueryWrapper<ActualMeasureItem> itemQw = new QueryWrapper<>();
        itemQw.eq("delete_state", 1);
        itemQw.isNull("tenant_id");
        List<ActualMeasureItem> itemLs = actualMeasureItemMapper.selectList(itemQw);
        Map<Long, List<ActualMeasureItem>> groupBy = new HashMap<>();
        if (CollectionUtil.isNotEmpty(itemLs)) {
            groupBy = itemLs.stream().collect(Collectors.groupingBy(ActualMeasureItem::getMeasureTypeId));
        }
        if (CollectionUtil.isNotEmpty(actualMeasureTypeLs)) {
            Date now = cn.hutool.core.date.DateUtil.date();
            Map<Long, List<ActualMeasureItem>> finalGroupBy = groupBy;
            actualMeasureTypeLs.stream().forEach(t -> {
                Long oldMeasureTypeId = t.getId();
                t.setId(null);
                t.setTenantId(tenant.getId());
                t.setCreateTime(now);
                t.setModifyTime(now);
                t.setDeleteState(1);
                //20221206增加设置租户分类的原始id
                t.setEnterpriseTypeId(oldMeasureTypeId);
                //找父级
                if(t.getParentId().intValue() != 0){
                    QueryWrapper<ActualMeasureType> parentQw = new QueryWrapper();
                    String fullName = t.getFullName();
                    String parentName = fullName.substring(0,fullName.substring(0,fullName.length()-1).lastIndexOf("/"));
                    parentQw.eq("delete_state",1);
                    parentQw.eq("full_name",parentName + "/");
                    parentQw.eq("level",t.getLevel() - 1);
                    parentQw.eq("tenant_id",t.getTenantId());
                    ActualMeasureType parentType = actualMeasureTypeMapper.selectOne(parentQw);
                    if(parentType != null){
                        t.setParentId(parentType.getId());
                        t.setFullId(parentType.getFullId());
                    }
                }

                saveUpdateFullId(t);

                List<ActualMeasureItem> typeItemLs = finalGroupBy.get(oldMeasureTypeId);
                if (CollectionUtil.isNotEmpty(typeItemLs)) {
                    typeItemLs.stream().forEach(d -> {
                        //20221206增加设置租户算法的原始id
                        d.setEnterpriseItemId(d.getId());
                        d.setId(null);
                        d.setMeasureTypeId(t.getId());
                        d.setTenantId(tenant.getId());
                        d.setCreateTime(now);
                        d.setModifyTime(now);
                        d.setDeleteState(1);
                        actualMeasureItemMapper.insert(d);
                    });
                }
            });
        }
    }

    private void saveUpdateFullId(ActualMeasureType levelType) {
        //先查询
        QueryWrapper<ActualMeasureType> qw = new QueryWrapper();
        qw.eq("delete_state",1);
        qw.eq("full_name",levelType.getFullName());
        qw.eq("level",levelType.getLevel());
        qw.eq("tenant_id",levelType.getTenantId());
        ActualMeasureType inDbType = actualMeasureTypeMapper.selectOne(qw);


        if (inDbType != null){
            BeanUtil.copyProperties(inDbType,levelType, CopyOptions.create().setIgnoreNullValue(true));
        }else{
            actualMeasureTypeMapper.insert(levelType);
            int level = levelType.getLevel();
            if (level == 1) {
                levelType.setFullId("/" + levelType.getId() + "/");
            } else {
                levelType.setFullId(levelType.getFullId() + levelType.getId() + "/");
            }
            actualMeasureTypeMapper.updateById(levelType);
        }
    }
}
